package org.lex.jadfront.core;

import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

import org.lex.io.utils.FileUtils;
import org.lex.io.utils.Unzip;
import org.lex.jadfront.util.AppStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JadJar {

	private Logger log = LoggerFactory.getLogger(JadJar.class);

	public void decompile(File inputJarFile, File outputDirectory, String... args) throws IOException {
		File tmpDir = this.createTmpDir(inputJarFile);
		log.info("tmpdir=" + tmpDir + ", jar=" + inputJarFile);

		log.info("unzip " + inputJarFile);
		new Unzip(inputJarFile, tmpDir).unzip();

		Stack<File> stack = new Stack<File>();
		stack.push(tmpDir);
		Queue<File> queue = new LinkedList<File>();
		while (false == stack.isEmpty()) {

			File top = stack.pop();
			if (top.isFile()) {
				queue.offer(top);
			} else if (top.isDirectory()) {
				File[] files = top.listFiles();
				for (File file : files) {
					if (file.isFile()) {
						queue.offer(file);
					} else if (file.isDirectory()) {
						stack.push(file);
					}
				}
			}
		}

		String baseDir = tmpDir.getAbsolutePath();
		JadOptions opt = new JadOptions();
		while (false == queue.isEmpty()) {
			File classFile = queue.poll();
			if (false == this.isClassFile(classFile)) {
				continue;
			}

			String classDir = classFile.getParent();
			String srcDir = classDir.substring(baseDir.length());
			File out = new File(outputDirectory, srcDir);
			new Jad().decompile(classFile, out, opt);
		}
	}

	private File createTmpDir(File inputJar) {
		File appTmp = AppStorage.getApplicationTmpDir();
		File taskTmp = new File(appTmp, inputJar.getName() + "." + System.currentTimeMillis());
		FileUtils.createFolder(taskTmp);
		return taskTmp;
	}

	private boolean isClassFile(File file) {
		String name = file.getName().toLowerCase();
		if (-1 == name.indexOf('$') && name.endsWith(".class")) {
			return true;
		} else {
			return false;
		}
	}
}
